import os
from datetime import datetime
ACTVHH_DIR = r"";
RETTXN_DIR = r"";
CDTDLG_DIR = r"";

WIDE_RECORDWES = []
ACTVHH = []

RETTXN = []

CDTDLG = []
RECORD_TAIL = '^ENDROW'



# 读取文件进行初始化
def init_data():
    global  RETTXN, CDTDLG
    RETTXN = []
    CDTDLG = []

    # 初始化 ACTVHH 数据池
    # 循环读取 actvhh 目录下的所有记录
    # 读取 RETTXN 文件
    # 遍历目录下所有文件（忽略子目录）
    for filename in os.listdir(RETTXN_DIR):
        file_path = os.path.join(RETTXN_DIR, filename)
        # 跳过子目录，只处理文件
        if not os.path.isfile(file_path):
            continue
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                for line in f:
                    # 检查行是否以 "^row" 结尾（自动忽略行尾换行符）
                    if line.rstrip('\n\r').endswith(RECORD_TAIL):
                        # 去除换行符后按 '|' 分割
                        fields = line.rstrip('\n\r').split('|')
                        RETTXN.append(fields)
        except Exception as e:
            print(f"⚠️ 跳过文件 {filename}（无法读取）: {e}")

    print(f'✅ 共加载 {len(RETTXN)} 条以 "{RECORD_TAIL}" 结尾的有效记录')

    # 读取 CDTDLG 文件
    for filename in os.listdir(CDTDLG_DIR):
        file_path = os.path.join(CDTDLG_DIR, filename)
        # 跳过子目录，只处理文件
        if not os.path.isfile(file_path):
            continue
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                for line in f:
                    # 检查行是否以 "^row" 结尾（自动忽略行尾换行符）
                    if line.rstrip('\n\r').endswith(RECORD_TAIL):
                        # 去除换行符后按 '|' 分割
                        fields = line.rstrip('\n\r').split('|')
                        CDTDLG.append(fields)
        except Exception as e:
            print(f"⚠️ 跳过文件 {filename}（无法读取）: {e}")

    print(f'✅ 共加载 {len(CDTDLG)} 条以 "{RECORD_TAIL}" 结尾的有效记录')

    # 构建RETTXN账号查找字典
    build_rettxn_index(1)
    print(f'成功构建RETTXN账号查找字典')
    # 构建CDTDLG 账号查找字典
    build_cdtdlg_index(10)
    print(f'成功构建CDTDLG账号查找字典')

    return


def read_actvhh_records(root_dir, record_tail=RECORD_TAIL):
    """
    生成器：逐行读取 root_dir 下所有文件，yield 以 record_tail 结尾的有效记录（字段列表）

    参数:
        root_dir (str): 数据文件目录路径
        record_tail (str): 有效行结尾标记，默认 '^row'

    产出:
        List[str]: 每条有效记录的字段列表（已 split('|')）
    """
    for filename in os.listdir(root_dir):
        file_path = os.path.join(root_dir, filename)

        # 跳过子目录
        if not os.path.isfile(file_path):
            continue

        print(f"🔍 正在处理文件: {filename}")

        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore', buffering=1024 * 1024) as f:
                for line in f:
                    # 去除行尾换行符后判断结尾
                    stripped_line = line.rstrip('\n\r')
                    if stripped_line.endswith(record_tail):
                        # 分割字段并 yield
                        yield stripped_line.split('|')
        except Exception as e:
            print(f"⚠️ 跳过文件 {filename}（读取错误）: {e}")

# 预处理：构建账号 -> 记录列表 的映射（一次性）
RETTXN_INDEX = {}

# def build_rettxn_index(account_index: int = 0):
#     """构建 RETTXN 账号索引"""
#     global RETTXN_INDEX
#     RETTXN_INDEX = {}
#     for record in RETTXN:
#         if len(record) > account_index:
#             acc = record[account_index]
#             if acc not in RETTXN_INDEX:
#                 RETTXN_INDEX[acc] = []
#             RETTXN_INDEX[acc].append(record)

def build_rettxn_index(account_index: int = 0):
    global RETTXN_INDEX
    RETTXN_INDEX = {}
    for idx, record in enumerate(RETTXN):
        if len(record) > account_index:
            acc = record[account_index]
            if acc not in RETTXN_INDEX:
                RETTXN_INDEX[acc] = []
            RETTXN_INDEX[acc].append(idx)  # 保存下标，而非 record 本身
# # 使用索引查找（O(1)）
# def find_rettxn_by_account_fast(account: str):
#     return RETTXN_INDEX.get(account, [None])[0]  # 返回第一条
def find_rettxn_by_account(account: str):
    """
    根据账号查找 RETTXN 中的第一条匹配记录（通过索引间接获取）
    返回：字段列表（list） 或 None（未找到）
    """
    indices = RETTXN_INDEX.get(account)
    if indices and len(indices) > 0:
        return RETTXN[indices[0]]  # 返回第一条记录
    return None

# 预处理：构建账号 -> 记录列表 的映射（一次性）
CDTDLG_INDEX = {}

# def build_cdtdlg_index(account_index: int = 0):
    # """构建 CDTDLG 账号索引"""
    # global CDTDLG_INDEX
    # CDTDLG_INDEX = {}
    # for record in CDTDLG:
    #     if len(record) > account_index:
    #         acc = record[account_index]
    #         if acc not in CDTDLG_INDEX:
    #             CDTDLG_INDEX[acc] = []
    #         CDTDLG_INDEX[acc].append(record)


""" 构建 CDTDLG 账号索引：以 record[account_index] 为键，
       值为该记录在全局列表 CDTDLG 中的下标（索引）列表。
       例如：CDTDLG_INDEX['123456'] = [0, 3, 7]
       表示账号 '123456' 出现在 CDTDLG 的第 0、3、7 条记录中。
"""
def build_cdtdlg_index(account_index: int = 0):
    global CDTDLG_INDEX
    CDTDLG_INDEX = {}
    for idx, record in enumerate(CDTDLG):
        if len(record) > account_index:
            acc = record[account_index]
            if acc not in CDTDLG_INDEX:
                CDTDLG_INDEX[acc] = []
            CDTDLG_INDEX[acc].append(idx)  # 保存下标，而非 record 本身

# # 使用索引查找（O(1)）
# def find_cdtdlg_by_account_fast(account: str):
#     return CDTDLG_INDEX.get(account, [None])[0]  # 返回第一条

def find_cdtdlg_by_account(account: str):
    """
    根据账号查找 CDTDLG 中的第一条匹配记录（通过索引间接获取）
    返回：字段列表（list） 或 None（未找到）
    """
    indices = CDTDLG_INDEX.get(account)
    if indices and len(indices) > 0:
        return CDTDLG[indices[0]]  # 返回第一条记录
    return None

# 全局索引字典（按需构建）
# CDTDLG_BY_CARD = {}      # 卡号 -> 记录列表
# def build_cdtdlg_index(key_index: int, index_name: str = "custom"):
#     """
#     为 CDTDLG 按指定字段构建索引字典
#
#     参数:
#         key_index (int): 用作 key 的字段索引（从0开始）
#         index_name (str): 索引名称（用于返回或存储）
#
#     返回:
#         Dict[str, List[List[str]]]: key -> 匹配记录列表
#     """
#     index_dict = {}
#     for record in CDTDLG:
#         if len(record) > key_index:
#             key = record[key_index]
#             if key not in index_dict:
#                 index_dict[key] = []
#             index_dict[key].append(record)
#     return index_dict
#
#
# # 快捷函数：按卡号构建索引（假设卡号在索引 0）
# def build_cdtdlg_by_card(card_index: int = 0):
#     global CDTDLG_BY_CARD
#     CDTDLG_BY_CARD = build_cdtdlg_index(card_index, "card")
#
#
# # 快捷函数：按商户号构建索引（假设商户号 MCNUM 在索引 13 → 第14个字段）
# def build_cdtdlg_by_mcnum(mcnum_index: int = 13):
#     global CDTDLG_BY_MCNUM
#     CDTDLG_BY_MCNUM = build_cdtdlg_index(mcnum_index, "mcnum")
#
#
# # 查找函数：通过卡号获取 CDTDLG 记录（返回第一条）
# def find_cdtdlg_by_card(cardno: str):
#     records = CDTDLG_BY_CARD.get(cardno, [])
#     return records[0] if records else None
#
#
# # 查找函数：通过商户号获取 CDTDLG 记录（返回第一条）
# def find_cdtdlg_by_mcnum(mcnum: str):
#     records = CDTDLG_BY_MCNUM.get(mcnum, [])
#     return records[0] if records else None


# 设计分隔符
DELIMITER = '|'
MAX_SIZE = 500 * 1024 * 1024  # 500MB（先别用5GB！）
WIDE_NAME = ""

# -------------- 1. 尾部 JSON 模板 --------------
TAIL_JSON_TEMPLATE = {
    "TabName"        : "dep_trade_pro",
    "AssemblyID"     : "NEW_JL00_P6",
    "PlatformID"     : "P6",
    "IsSplitFlag"    : "0",
    "MechanismID"    : "000008",
    "DataStartDate"  : "20251010",
    "DataEndDate"    : "20251010",
    "IncID"          : "0",
    # 真实条数等关闭前再填
    "RecNum"         : "{rec_num}",
    "Sep"            : DELIMITER,
    "CycFlag"        : "D",
    "TableGenType"   : "0",
    "GenTime"        : "{gen_time}"
}


# 设计获取数据填充到宽表调用接口
def proceing_data():
    deployment_time = datetime.now().strftime('%Y%m%d%H%M%S')  # ✅ 统一投产时间
    output_file = None
    file_index = 1
    current_size = 0
    # 读取ACTVHH 文本文件 并且解决ACTVHH 可处理的字段

    for fields in read_actvhh_records(ACTVHH_DIR):

        # fields = ['0001', 'T123', 'CNY^row']
        # 在这里做宽表映射、写文件、入库等
        wide_line = [""] * 140
    #     账号 account
        account = None
    # 数据解析
    # 1 客户号 在ACTVHH表中第8个字段
        wide_line[0] = fields[8]
    # 2 账号 使用ACTVHH表中ORGID3(7),CUSIDT(8),APCODE(9),CURCDE(10) 这四个字段拼接而成
        wide_line[1] = fields[7]+fields[8]+fields[9]+fields[10]
        account = wide_line[1]
    # 3 旧帐号 存取2 中的内容
        wide_line[2] = account
    # 4 账号类型  判断RETTXN(ACTTYP 6)
        if len(account) == 18:
            # 对公账户
            wide_line[3] = '01'
        elif len(account) == 15:
            # 对私15位：看第7-8位（索引6:8）
            tmp_type = account[6:8]
            if tmp_type == '01':
                wide_line[3] = '023'
            elif tmp_type == '02':
                wide_line[3] = '021'
            else:
                wide_line[3] = ""  # 或 ''，根据需求
        elif len(account) == 19:
            # 对私19位：先看第10-11位（索引9:11）
            sub_type = account[9:11]
            if sub_type == '05':
                wide_line[3] = '022'
            elif sub_type == '23':
                wide_line[3] = '024'
            else:
                # 此处无法仅通过 account 字符串判断是否为活期/定期（需查表）
                # 若你只有 account 字符串、无外部表，则只能留空或设默认
                # 假设你无法访问 retsav/retfix 表，则无法确定 '03'/'04'
                # 可选：保留原逻辑中无法判断的情况为 None
                wide_line[3] = ""
        else:
            wide_line[3] = ""
    # 5 查询卡号 通过账号查询CDTDLG 默认 “00000”
        # 默认值
        wide_line[4] = "00000"
        record = find_cdtdlg_by_account(account)
        if record is not None and len(record) > 8:
            candidate = record[8].strip()
            if candidate:  # 非空、非空白
                wide_line[4] = candidate
    # 6 卡类型  使用卡号匹配 cdtdlg 存在05 不存在 None
        wide_line[5] = "99"
        record = find_cdtdlg_by_account(account)
        if record :
            wide_line[5] = "05"
    # 7 机构号 使用ACTVHH表中的 ORGIDT(1)
        if fields[1]:
            wide_line[6] = fields[1].strip()
    # 8 交易类型 使用CDTDLG表中的 TXNTYP(7)
        record = find_cdtdlg_by_account(account)
        if record :
            wide_line[7] = record[7].strip()
    # 9 借贷标记 值为‘D’ RETTXN中 若DRAMNT（19）>0,则借方,若CRAMNT（20）>0，则贷方
        record = find_rettxn_by_account(account)
        if record :
            dramnt = int(record[19])
            cramnt = int(record[20])
            if dramnt >= cramnt:
                wide_line[8] = "D"
            else:
                wide_line[8] = "C"
    # 10 币种  -- ACTVHH(CURCDE 10) CNY
        wide_line[9] = fields[10]
    # 11 交易金额 -- 默认0 ACTVHH(TXNAMT 11) CDTDLG(TXNMAT) 默认 100.00
        wide_line[10] = fields[11]
    # 12 交易余额 -- ACTVHH(BOKBAL 12) RETTXN(PSTBAL 22) 默认 100.00
        wide_line[11] = fields[12]
        wide_line[11] = find_rettxn_by_account_fast(account)[22]
    # 13 交易时间 -- ACTVHH(ERYDAT 5) RETTXN(TXNDAT 2) 采用格式YYYYMMDDhhmmss 补0
        wide_line[12] = fields[5]
    # 14 交易流水 --RETTXN(TXNSEQ 5)
        wide_line[13] = find_rettxn_by_account_fast(account)[5]
    # 15 交易代码 -- RETTXN(TXNCDE 10)
        wide_line[14] = find_rettxn_by_account_fast(account)[10]
    # 22 交易摘要   -- ACTVHH(FURINF 15),RETTXN(TXNREF 35)
        wide_line[21] = fields[15]
    # 23 交易网点名称 -- ACTVHH(TXNBAK 23) RETTXN(AGTIDT 15) -》ACTORG(ORGIDT )
        wide_line[22] = fields[22]
    # 24 日志号  -- ACTVHH (VCHSET 3)
        wide_line[23] = fields[3]
    # 27 现金标识 -- RETTXN (CSHFLG 31) ，CDTDLG(DEVTYP 28)
        wide_line[26] = find_rettxn_by_account_fast(account)[31]
    # 28 终端号 -- RETTXN (TRNNUM 4) CDTDLG(TERMID 15)
        wide_line[27] = find_rettxn_by_account_fast(account)[4]
    # 29 交易是否成功 -- RETTXN (RVSFLG 27)
        wide_line[28] = find_rettxn_by_account_fast(account)[27]
    # 31 商户名称 -- CDTDLG（MCNUM 14）
        wide_line[30] = find_cdtdlg_by_account_fast(account)[14]
    # 32 商户号   -- CDTDLG (MCNUM 14)  RETTXN（卡号 日期 柜员 流水）与CDTDLG匹配
        wide_line[31] = find_cdtdlg_by_account_fast(account)[14]
    # 35 交易柜员号  -- ACTVHH(TLRNUM 2) RETTXN(17)
        wide_line[34] = fields[2]
    # 36 备注     -- CDTDLG(DLGMRK )

    # 37 本方账号
    # 38 本方卡号
    # 127 源入湖物理文件名 --
    # 128 源入湖表名 --账户对应的ACTVHH 或者 RETTXN
    # 129 源系统 --默认使用 SBS
    # 130 源归属编号  -- 使用机构号
    # 131 原归属地   --
    # 132 源时间节点 -- 默认使用 20100815 蓝图上收时间节点

    # 133 数据来源 -- 默认使用 ODMS
        wide_line[33] = "ODMS"
    # 134 交易记录属性 -- ACTVHH 01, RETTXN 02
        wide_line[133] = "01"
    # 138 跨行标识 --默认使用 None
        wide_line[137] = "2"
    # 139 交易动帐标识 --默认使用 1
        wide_line[138] = "1"
    # 140 系统日期 --调用时间接口函数 保存当前时间
        wide_line[139] = datetime.now().strftime('%Y%m%d%H%M%S')

    # 设计个宽表大小5G输出文件，生成最终项目文件
    # 1 每一条wide_line 目前是列表 要转为每个字段以“|”分隔的字符串最后也要添加
    # 2 添加wide_line 到WIDE_RECORDERS 中
    # 3 判断WIDE_RECORDERS 大小达到5G 输出文件，清空WIDE_RECORDRS
        # --- 写入文件（流式，不缓存）---
        line_str = DELIMITER.join(str(x) if x is not None else '' for x in wide_line) + '\n'
        line_bytes = line_str.encode('utf-8')
        # 检查是否需要新建文件
        if output_file is None or current_size + len(line_bytes) > MAX_SIZE:
            if output_file:
                output_file.close()
            filename = f"{WIDE_NAME}{file_index:03d}.txt"
            print(f"📁 创建新文件: {filename}")
            output_file = open(filename, 'wb')
            file_index += 1
            current_size = 0
        output_file.write(line_bytes)
        current_size += len(line_bytes)

    return




def main():

    # 创建长度为140 的列表
    data = [None] * 140
    # 把列表转化成为字符串 并且添加分隔符
    line = '|'.join(map(str, data))+'|'

    print(data)


    print(line)



    return



if __name__ == '__main__':
    main()